//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved

#pragma once

extern const float camera_z_far;
extern const float camera_z_near;
extern const float camera_z_step;
extern const float camera_move_min;
extern const float camera_move_max;
extern const float camera_move_speed;


// A simple camera class.
ref class BasicCamera
{
internal:
    float3 m_position;      // the position of the camera
    float3 m_direction;     // the unit vector of the viewing direction
    float4x4 m_view;        // view matrix
    float4x4 m_projection;  // projection matrix


    void GetViewMatrix(_Out_ float4x4 *viewMatrix);
    void GetProjectionMatrix(_Out_ float4x4 *projectionMatrix);

    // this method updates the view matrix based on new position and focus coordinates
    void SetViewParameters(
        _In_ float3 eyePosition,    // the position of the camera
        _In_ float3 lookPosition,   // the point the camera should look at
        _In_ float3 up              // the durection vector for up
        );

    // this method updates the projection matrix based on new parameters
    void SetProjectionParameters(
        _In_ float minimumFieldOfView,  // the minimum horizontal or vertical field of view, in degrees
        _In_ float aspectRatio,         // the aspect ratio of the projection (width / height)
        _In_ float nearPlane,           // depth to map to 0
        _In_ float farPlane             // depth to map to 1
        );
};


ref class Camera2D : public BasicCamera
{
internal:
	enum CameraMoveFlag
	{
		VerticalDown = 0,
		VerticalUp,
		HorizontalLeft,
		HorizontalRight,
	};

	Camera2D();

	void ZoomIn(float z_offset = camera_z_step);

	void ZoomOut(float z_offset = camera_z_step);

	void Update(float frame_time);

	void SetMoveFlag(uint flag);

	void Move(float2 move_offset = float2(camera_move_speed, camera_move_speed));

	void SetPosition(const float3& position);

private:
	void UpdateViewParameters();


private:	
	float3 m_xyz;

	uint m_move_flags;
};